package com.zp.viewpractice.BasePractice;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by izp on 2017/7/22.
 */

public class PracticeLayout extends ViewGroup {


    public PracticeLayout(Context context) {
        super(context);
    }

    /**
     * 第一步
     * @param context
     * @param attrs
     */
    public PracticeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PracticeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public PracticeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }


    /**
     * 第二步
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     *
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        /**
         * 这是如果不改变控件的大小，那么这里就必须调用，比如只是获取各种宽高，不做操作
         */
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        /**
         *如果有根据传进来的宽高进行修改，最后确定一个真实的宽高，这里就要调用这个。
         */
        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),MeasureSpec.getSize(heightMeasureSpec));
    }

    /**
     * 第三步
     * 因为onMeasure只是对View本身的宽高进行处理，而onSizeChange,是这个父View会对子View产生影响，最终能确定View大小是在这里
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    }


    /**
     * 第四步
     * @param b
     * @param i
     * @param i1
     * @param i2
     * @param i3
     */
    @Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
        for (int n=0;i<getChildCount();n++){
            View child = getChildAt(n);
            if (null==child)
                continue;
            /**
             * left,child
             */
            child.layout(i,i1,i2,i3);//left是子View距离父View的左边的距离，right是子View的右边距离父View左边的距离，
        }
    }

    /**
     * 第五步
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

    }

    /**
     * 绘制颜色的几个方法
     * @param canvas
     */
    private void drawColor(Canvas canvas){
        canvas.drawColor(Color.BLUE);
        canvas.drawRGB(0,0,0);
        canvas.drawARGB(0,0,0,0);
    }

    private Paint getBasePaint(){
        Paint paint = new Paint();
        paint.setColor(Color.BLACK);//设置画笔颜色
        paint.setStyle(Paint.Style.FILL);//设置绘制状态为填充
        paint.setStrokeWidth(10f);//设置画笔的宽度，10px，
        return paint;
    }
    private Paint getStrokePaint(){
        Paint paint = new Paint();
        paint.setColor(Color.BLACK);//设置画笔颜色
        paint.setStyle(Paint.Style.STROKE);//设置绘制状态为填充
        paint.setStrokeWidth(10f);//设置画笔的宽度，10px，
        return paint;
    }

    /**
     * 绘制各种形状
     * @param canvas
     */
    private void drawShape(Canvas canvas){
        canvas.drawPoint(200,200,getBasePaint());//在当前View的 200和200，这个相对位置绘制一个点
        canvas.drawPoints(new float[]{500,500,
        500,600,500,700},getBasePaint());//这个数据居然不用二维数组，让我有点诧异啊


        canvas.drawLine(300,500,500,600,getBasePaint());//一个线有两个点，所以确定两个点，传入画笔就行了
        canvas.drawLines(new float[]{100,200,    200,200,
        100,300,     200,300},getBasePaint());

//        绘制矩形
    }

    /**
     * 绘制矩形，三种方法的结果基本一样
     * 确定 坐上点的坐标和右下点的坐标
     * @param canvas
     */
    private void drawRact(Canvas canvas){
// 第一种
        canvas.drawRect(100,100,800,400,getBasePaint());

        // 第二种
        Rect rect = new Rect(100,100,800,400);
        canvas.drawRect(rect,getBasePaint());

        // 第三种
        RectF rectF = new RectF(100f,100f,800f,400f);
        canvas.drawRect(rectF,getBasePaint());

    }
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void drawRoundReact(Canvas canvas){
// 第一种
        RectF rectF = new RectF(100,100,800,400);
        canvas.drawRoundRect(rectF,30,30,getBasePaint());

        // 第二种,但鉴于第二种方法在API21的时候才添加上，所以我们一般使用的都是第一种。
        canvas.drawRoundRect(100,100,800,400,30,30,getBasePaint());

        Paint paint = getBasePaint();
        // 矩形
        RectF rectF2 = new RectF(100,100,800,400);

        // 绘制背景矩形
        paint.setColor(Color.GRAY);
        canvas.drawRect(rectF,paint);

        // 绘制圆角矩形
        paint.setColor(Color.BLUE);
        canvas.drawRoundRect(rectF,700,400,paint);//700，400是view上距离left 和top 的一个点，并且left和top作为一个椭圆的两个半径，每个角都是椭圆，
        /**
         * 实际上在rx为宽度的一半，ry为高度的一半时，刚好是一个椭圆，通过上面我们分析的原理推算一下就能得到，而当rx大于宽度的一半，
         * ry大于高度的一半时，实际上是无法计算出圆弧的，所以drawRoundRect对大于该数值的参数进行了限制(修正)，凡是大于一半的参数均按照一半来处理。
         */
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void drawOval(Canvas canvas){
//        相对于绘制圆角矩形，绘制椭圆就简单的多了，因为他只需要一个矩形矩形作为参数:
        // 第一种
        RectF rectF = new RectF(100,100,800,400);
        canvas.drawOval(rectF,getBasePaint());

        // 第二种,也是需要21以上api
        canvas.drawOval(100,100,800,400,getBasePaint());
//        绘制椭圆实际上就是绘制一个矩形的内切图形，
    }

    /**
     * 画圆，很简单，确定一个点，然后确定一个半径。
     * @param canvas
     */
    private void drawCircle(Canvas canvas){
        canvas.drawCircle(500,500,400,getBasePaint());
    }


    /**
     * @param canvas
     * 绘制圆弧path
     */
    private void drawPathArc(Canvas canvas){
        canvas.translate(getWidth()/2,getHeight()/2);//把坐标原点移动到屏幕中心
        canvas.scale(1,-1);//翻转Y坐标，变成原点向上为正向下为负，向右为正向左为负。
        Path path = new Path();//path默认就是描边、黑色
        path.lineTo(100,100);//原点到100，100点之间连线。

        RectF oval = new RectF(0,0,300,300);//先创建一个矩形，这个矩形是，顺时针，00点，0，300点，300，300点最后是300，0点。
        //通过椭圆正切获取椭圆。
        path.addArc(oval,0,270);//oval画成圆弧，然后当道path中
//        这个和上面的等价
        path.arcTo(oval,0,270,true);
        canvas.drawPath(path,getStrokePaint());
    }
}
